/**
 * Created on 2007-05-16 12:34
 */
package game.frames;

import game.Settings;
import game.input.InputManager;

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.HierarchyBoundsListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.JPanel;

/**
 * @author David Wallin
 * 
 * Basic abstract class for frames in a multiple frames system.
 * Override the actions methods that are of interest.
 * Implement the initializeComponent() method where the GUI of the
 * derived component should be defined
 */
public abstract class BasicFrame extends JPanel implements ActionListener,
		MouseListener, MouseMotionListener,
		MouseWheelListener, PropertyChangeListener,
		ComponentListener, FocusListener, HierarchyBoundsListener,
		HierarchyListener, InputMethodListener, KeyListener, ContainerListener
{
	protected int									m_Width;
	protected int									m_Height;
	protected ArrayList<FrameSwitchListener>		m_FrameSwitchListeners;
	
	/**
	 * The one instance of the input manager
	 */
	protected InputManager							m_InputManager;
	/**
	 * The one instance of the settings
	 */
	protected Settings								m_Settings;
	
	/**
	 * Constructor, calls super with the title as argument.
	 * Adds this as listener to all the available action firerers
	 * Calls the abstract method initializeComponent() that shouldbe
	 * implemented in the derived class
	 * 
	 * @param title The title of this frame
	 */
	protected BasicFrame()
	{
		this(new FlowLayout());
	}
	
	protected BasicFrame(LayoutManager lm)
	{
		this(lm, 0, 0);
	}
	
	protected BasicFrame(int width, int height)
	{
		this(new FlowLayout(), width, height);
	}
	
	protected BasicFrame(LayoutManager lm, int width, int height)
	{
		super(lm);
		
		if((width > -1) || (height > -1))
		{
			m_Width = width;
			m_Height = height;
			this.setSize(width, height);
		}
		
		this.addComponentListener(this);
		this.addContainerListener(this);
		this.addFocusListener(this);
		this.addHierarchyBoundsListener(this);
		this.addHierarchyListener(this);
		this.addInputMethodListener(this);
		this.addKeyListener(this);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addMouseWheelListener(this);
		this.addPropertyChangeListener(this);
		
		m_FrameSwitchListeners = new ArrayList<FrameSwitchListener>();
		m_InputManager = InputManager.INSTANCE;
		m_Settings = Settings.INSTANCE;
		
		initializeComponent();
	}
	
	/**
	 * Adds a FrameSwitchListener to this frame
	 * 
	 * @param l The FrameSwitchListener to add
	 */
	public void addFrameSwitchListener(FrameSwitchListener l)
	{
		if(!m_FrameSwitchListeners.contains(l))
		{
			m_FrameSwitchListeners.add(l);
		}
	}
	
	/**
	 * Removes a FrameSwitchListener to this frame
	 * 
	 * @param l The FrameSwitchListener to remove
	 */
	public void removeFrameSwitchListener(FrameSwitchListener l)
	{
		if(m_FrameSwitchListeners.contains(l))
		{
			m_FrameSwitchListeners.remove(l);
		}
	}
	
	public void displayFrame(boolean display)
	{
		int components = this.getComponentCount();
		
		for(int i = 0; i < components; i++)
		{
			this.getComponent(i).setVisible(display);
		}
	}
	
	protected void updateFrameSwitchListeners(Frames frameToSwitchTo)
	{
		Iterator<FrameSwitchListener> it = m_FrameSwitchListeners.iterator();
		
		while(it.hasNext())
		{
			it.next().switchCalled(frameToSwitchTo);
		}
	}
	
	protected void addComponent(Component component, GridBagLayout gridBag, GridBagConstraints constraints)
	{
		gridBag.setConstraints(component, constraints);
		this.add(component);
	}
	
	/**
	 * Should set up the GUI of the component
	 */
	protected abstract void initializeComponent();
	
	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
	 */
	public void mouseClicked(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
	 */
	public void mouseEntered(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
	 */
	public void mouseExited(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
	 */
	public void mousePressed(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
	 */
	public void mouseReleased(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
	 */
	public void mouseDragged(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
	 */
	public void mouseMoved(MouseEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
	 */
	public void mouseWheelMoved(MouseWheelEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
	 */
	public void propertyChange(PropertyChangeEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.ComponentEvent)
	 */
	public void componentHidden(ComponentEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent)
	 */
	public void componentMoved(ComponentEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ComponentListener#componentResized(java.awt.event.ComponentEvent)
	 */
	public void componentResized(ComponentEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent)
	 */
	public void componentShown(ComponentEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent)
	 */
	public void focusGained(FocusEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
	 */
	public void focusLost(FocusEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.HierarchyBoundsListener#ancestorMoved(java.awt.event.HierarchyEvent)
	 */
	public void ancestorMoved(HierarchyEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.HierarchyBoundsListener#ancestorResized(java.awt.event.HierarchyEvent)
	 */
	public void ancestorResized(HierarchyEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.HierarchyListener#hierarchyChanged(java.awt.event.HierarchyEvent)
	 */
	public void hierarchyChanged(HierarchyEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.InputMethodListener#caretPositionChanged(java.awt.event.InputMethodEvent)
	 */
	public void caretPositionChanged(InputMethodEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.InputMethodListener#inputMethodTextChanged(java.awt.event.InputMethodEvent)
	 */
	public void inputMethodTextChanged(InputMethodEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
	 */
	public void keyPressed(KeyEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
	 */
	public void keyReleased(KeyEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
	 */
	public void keyTyped(KeyEvent event)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ContainerListener#componentAdded(java.awt.event.ContainerEvent)
	 */
	public void componentAdded(ContainerEvent arg0)
	{
	}
	
	/* (non-Javadoc)
	 * @see java.awt.event.ContainerListener#componentRemoved(java.awt.event.ContainerEvent)
	 */
	public void componentRemoved(ContainerEvent arg0)
	{
	}
}
